﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace V32Assembler
{
    public struct Register
    {
        public static readonly Register None, A, B, C, D, E, F, G, T, U, V, W, X, Y, Z, S, IP, SP, FL;

        static Register()
        {
            A = new Register(ArgSize.Byte);
            B = new Register(ArgSize.Byte);
            C = new Register(ArgSize.Byte);
            D = new Register(ArgSize.Byte);
            E = new Register(ArgSize.Byte);
            F = new Register(ArgSize.Byte);
            G = new Register(ArgSize.Byte);
            T = new Register(ArgSize.Word);
            U = new Register(ArgSize.Word);
            V = new Register(ArgSize.Word);
            W = new Register(ArgSize.Word);
            X = new Register(ArgSize.Word);
            Y = new Register(ArgSize.Word);
            Z = new Register(ArgSize.Word);
            S = new Register(ArgSize.Word);
            IP = new Register(ArgSize.Word);
            SP = new Register(ArgSize.Word);
            FL = new Register(ArgSize.Byte);

            None = new Register(ArgSize.Byte); // had to pick something
        }

        public ArgSize Size { get; private set; }
        public byte ByteRepr { get; private set; }

        private static byte currentByteRepr = 0;
        private Register(ArgSize size)
            : this()
        {
            Size = size;
            ByteRepr = currentByteRepr++;
        }

        public static Register FromString(string str)
        {
            switch (str.ToLower())
            {
                case "a": return A;
                case "b": return B;
                case "c": return C;
                case "d": return D;
                case "e": return E;
                case "f": return F;
                case "g": return G;
                case "t": return T;
                case "u": return U;
                case "v": return V;
                case "w": return W;
                case "x": return X;
                case "y": return Y;
                case "z": return Z;
                case "s": return S;
                case "ip": return IP;
                case "sp": return SP;
                case "fl": return FL;
                default: return None;
            }
        }

        public override string ToString()
        {
            if (this == A) return "A";
            else if (this == B) return "B";
            else if (this == C) return "C";
            else if (this == D) return "D";
            else if (this == E) return "E";
            else if (this == F) return "F";
            else if (this == G) return "G";
            else if (this == T) return "T";
            else if (this == U) return "U";
            else if (this == V) return "V";
            else if (this == W) return "W";
            else if (this == X) return "X";
            else if (this == Y) return "Y";
            else if (this == Z) return "Z";
            else if (this == S) return "S";
            else if (this == IP) return "IP";
            else if (this == SP) return "SP";
            else if (this == FL) return "FL";
            else return "[None]";
        }

        public static bool operator ==(Register reg1, Register reg2)
        {
            return reg1.ByteRepr == reg2.ByteRepr;
        }
        public static bool operator !=(Register reg1, Register reg2)
        {
            return !(reg1 == reg2);
        }
        public override bool Equals(object obj)
        {
            if (obj is Register)
                return this == (Register)obj;
            return obj.Equals(this);
        }
        public override int GetHashCode() { return ByteRepr; }
    }
}
